package com.lancoo.cvas.arrangecourse;

import cn.hutool.core.collection.CollUtil;
import com.lancoo.cvas.arrangecourse.entities.BaseRule;
import com.lancoo.cvas.entity.*;
import com.lancoo.cvas.mapper.RoomMapper;
import com.lancoo.cvas.pojo.common.Deleted;
import com.lancoo.cvas.pojo.common.FixType;
import com.lancoo.cvas.pojo.dto.*;
import com.lancoo.cvas.pojo.vo.WeekDateVo;
import com.lancoo.cvas.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: liufeng
 * @CreateTime: 2023-12-12  15:20
 * @Description:
 */
@Component
@Slf4j
public class ArrangeCourseDataSource {
    //课表排课计划
    @Resource
    @Lazy
    ScheduleService scheduleService;

    @Resource
    private RoomMapper roomMapper;

    @Resource
    @Lazy
    TaskInfoService taskInfoService;
    @Resource
    ScheduleConflictInfoService conflicService;

    @Resource
    BasicRuleService basicRuleService;


    /**
     * 场地禁排的信息
     *
     * @param schoolId 学校id
     * @param termId   学期id
     * @param campusId null全部
     * @return
     */
    public List<ArrangeRoomRuleDto> getRoomRuleList(Integer taskId, String schoolId, String termId, String campusId) {
        //实际数据
        List<ArrangeRoomRuleDto> roomRuleList = scheduleService.getArrangeRoomProhibit(taskId, schoolId, termId, campusId);
        if (roomRuleList == null || roomRuleList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getRoomRuleList: 排课教室禁排规则数据，获取失败~！！");
            return new ArrayList<>();
        }
        return roomRuleList;
        //测试数据
//        return dataService.getRoomRuleList(campusId);
    }

    public List<ArrangeTeacherRuleDto> getTeacherRuleList(Integer taskId, String schoolId, String termId) {
        //实际数据
        List<ArrangeTeacherRuleDto> teacherRuleList = scheduleService.getArrangeTeacherTime(taskId, schoolId, termId);
        if (teacherRuleList == null || teacherRuleList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getTeacherRuleList: 排课教师规则数据数据，获取失败~！！");
            return new ArrayList<>();
        }
        return teacherRuleList;
    }

    public List<ArrangeCourseRuleDto> getCourseRuleList(Integer taskId) {
        //实际数据
        List<ArrangeCourseRuleDto> courseRuleList = scheduleService.getArrangeCourseProhibit(taskId);
        if (courseRuleList == null || courseRuleList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getCourseRuleList: 排课课程规则数据，获取失败~！！");
            return new ArrayList<>();
        }
        return courseRuleList;
    }

    public List<ArrangeClassRuleDto> getclassRuleList(Integer taskId) {
        //实际数据
        List<ArrangeClassRuleDto> classRuleList = scheduleService.getArrangeClassProhibit(taskId);
        if (classRuleList == null || classRuleList.isEmpty()) {
            log.info("ArrangeClassDataSource--getClassRuleList: 排课行政班规则数据，获取失败~！！");
            return new ArrayList<>();
        }
        return classRuleList;
    }

    public List<ArrangeTeachingClassRuleDto> getTeachingClassRuleList(Integer taskId) {
        //实际数据
        List<ArrangeTeachingClassRuleDto> teachingClassRuleList = scheduleService.getArrangeTeachingClassProhibit(taskId);
        if (teachingClassRuleList == null || teachingClassRuleList.isEmpty()) {
            log.info("ArrangeClassDataSource--getClassRuleList: 排课行政班规则数据，获取失败~！！");
            return new ArrayList<>();
        }
        return teachingClassRuleList;
    }

    public List<ArrangeRoomDto> getRoomList(String schoolId, String term, String campusId) {
        //实际数据
        List<ArrangeRoomDto> roomList = roomMapper.getArrangeRoom(schoolId, term, campusId, Deleted.NOT.getCode());
        if (roomList == null || roomList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getRoomList: 排课教学班数据，获取失败~！！");
            return new ArrayList<>();
        }
        return roomList;
    }

    public List<ArrangePeriod> getTimeslotList(Integer taskId, String schoolId, String termId) {
        //实际数据
        List<ArrangePeriod> timeslotList = scheduleService.getArrangeTimeCode(taskId, schoolId, termId);
        if (timeslotList == null || timeslotList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getTimeslotList: 排课课时数据，获取失败~！！");
            return new ArrayList<>();
        }
        return timeslotList;
    }

    public List<ArrangeScheduleDto> getLockedScheduleList(Integer taskId, String campusId, Integer isLocked, Integer roomType) {
        //实际数据
        List<ArrangeScheduleDto> scheduleLockedList = scheduleService.getLockSchedule(taskId, campusId, isLocked, roomType);
        if (scheduleLockedList == null || scheduleLockedList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getLockedScheduleList: 排课已锁定的课表数据，获取失败~！！");
            return new ArrayList<>();
        }
        return scheduleLockedList;
    }


    public List<ArrangeScheduleDto> getScheduleListByTeachingClassIds(Integer taskId, String campusId, List<Long> teachingClassIds) {
        //实际数据
        List<ArrangeScheduleDto> scheduleLockedList = scheduleService.getScheduleListByTeachingClassIds(taskId, campusId, teachingClassIds);
        if (scheduleLockedList == null || scheduleLockedList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getLockedScheduleList: 排课教学班的课表数据，获取失败~！！");
            return new ArrayList<>();
        }
        return scheduleLockedList;
    }

    public WeekDateVo getTermWeeks(Integer taskId) {
        WeekDateVo weekDate = taskInfoService.countWeek(taskId);
        if (weekDate == null) {
            log.error("ArrangeCourseDataSource--getTermWeeks: 排课教学班数据获取失败~！！");
            return null;
        }
        return weekDate;
    }

    public List<ScheduleConflictInfo> getTeachingClassConflictList(Long teachingClassId) {
        List<ScheduleConflictInfo> conflictList = conflicService.lambdaQuery()
                .eq(ScheduleConflictInfo::getTeachingClassId, teachingClassId)
                .or()
                .eq(ScheduleConflictInfo::getClashTeachingClassId, teachingClassId)
                .eq(ScheduleConflictInfo::getDeleted, Deleted.NOT.getCode())
                .list();

        if (conflictList == null || conflictList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getTeachingClassConflictList: 指定教学班的冲突信息，获取为空~！！");
            return new ArrayList<>();
        }
        return conflictList;
    }

    /**
     * 批量删除冲突信息
     *
     * @param conflictList 待删除的冲突信息列表
     */
    public void removeConflictList(List<ScheduleConflictInfo> conflictList) {
        try {
            conflicService.removeBatchByIds(conflictList);
        } catch (Exception ex) {
            log.error("ArrangeCourseDataSource--removeConflictList: 删除冲突列表信息失败，原因：" + ex.getMessage());
        }
    }

    /**
     * 存储每轮排课的冲突信息
     *
     * @param updateList 需要更新冲突状态的教学班列表信息
     */
    public void updateScheduleState(List<ArrangeTeachingClassUpdate> updateList) {
        try {
            scheduleService.updateScheduleState(updateList);
        } catch (Exception ex) {
            log.error("ArrangeCourseDataSource--updateScheduleState: 更新教学班冲突状态信息失败，原因：" + ex.getMessage());
        }

    }

    /**
     * 批量更新冲突列表信息
     *
     * @param conflictList 待更新的冲突信息列表
     */
    public void updateAndAddConflictList(List<ScheduleConflictInfo> conflictList) {
        try {
            conflicService.saveOrUpdateBatch(conflictList);
        } catch (Exception ex) {
            log.error("ArrangeCourseDataSource--updateConflictList: 更新冲突列表信息失败，原因：" + ex.getMessage());
        }
    }


    /**
     * 获取排课选课的计划信息
     *
     * @param taskId 计划id
     * @return
     */
    public TaskInfo getTaskInfo(Integer taskId) {
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        if (taskInfo == null) {
            log.error("ArrangeCourseDataSource--getTaskInfo: 排课学期排课选课计划信息获取失败~！！");
            return null;
        }
        return taskInfo;
    }

    /**
     * 获取教学班信息列表
     *
     * @param taskId   学期计划id
     * @param campusId 校区id， null全部
     * @return
     */
    public List<ArrangeTeachingClassDto> getTeachingClassList(Integer taskId, String campusId) {
        //实际数据
        List<ArrangeTeachingClassDto> teachingClassList = scheduleService.getTeachingClassDate(taskId, campusId);
        if (teachingClassList == null || teachingClassList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getTeachingClassList: 排课教学班数据，获取失败~！！");
            return new ArrayList<>();
        }
        return teachingClassList;
        //测试数据
//        return dataService.getTeachingClassList(campusId);
    }

    /**
     * 获取基础规则
     *
     * @param schoolId 学校id
     * @param termId   学期id
     * @param taskId   学期计划id
     * @return
     */
    public List<RuleUsable> getBaseRuleList(String schoolId, String termId, Integer taskId) {
        //实际数据
        List<RuleUsable> baseRuleList = basicRuleService.getCurrent(taskId, schoolId, termId);
        if (baseRuleList == null || baseRuleList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getBaseRuleList: 排课基础规则数据，获取失败~！！");
            return new ArrayList<>();
        }
        return baseRuleList;
        //测试数据
//        return dataService.getBaseRuleList();
    }

    /**
     * 获取高级规则设置的教师规则信息
     *
     * @param taskId 排课选课计划id
     * @return
     */
    public RuleTeacherSetting getTeacherSetting(Integer taskId) {
        RuleTeacherSetting teacherSetting = basicRuleService.getTeacherSetting(taskId);
        if (teacherSetting == null) {
            log.error("ArrangeCourseDataSource--getTeacherSetting: 高级规则设置的教师规则信息获取失败~！！");
            return null;
        }

        return teacherSetting;
    }

    /**
     * 存储每轮排课的课程信息，即课表信息
     *
     * @param taskId    学期计划id
     * @param schedules 课表列表信息
     */
    public void addBathSchedule(Integer taskId, List<Schedule> schedules) {
        try {
            scheduleService.addBathSchedule(taskId, schedules);
        } catch (Exception ex) {
            log.error("ArrangeCourseDataSource--addBathSchedule: 插入课表数据失败，原因：" + ex.getMessage());
        }

    }

    /**
     * 存储每轮排课的冲突信息
     *
     * @param taskId            学期计划id
     * @param scheduleConflicts 冲突的课表列表信息
     */
    public void addBatchScheduleConflict(Integer taskId, List<ScheduleConflictInfo> scheduleConflicts) {
        try {
            scheduleService.addBatchScheduleConflict(taskId, scheduleConflicts, null);
        } catch (Exception ex) {
            log.error("ArrangeCourseDataSource--addBatchScheduleConflict: 插入冲突信息数据失败，原因：" + ex.getMessage());
        }

    }


    /**
     * @Description: 根据规则开关选出教学班的固排禁排信息
     * @Author: liufeng
     * @Date: 2024/1/2 11:19
     * @param baseRule: 基础规则
     * @param teachingClassRuleList: 教学班固排禁排规则
     * @return:
     */
    public List<ArrangeTeachingClassRuleDto> filterTeachingClassRule(BaseRule baseRule, List<ArrangeTeachingClassRuleDto> teachingClassRuleList) {
        //禁排开关
        if ("a".equals(baseRule.getTeachingClassRuleEnable())) {
            //不启用时删除本身禁排信息
            //以及教学班类型固排信息删除
            if (CollUtil.isNotEmpty(teachingClassRuleList)) {
                teachingClassRuleList = teachingClassRuleList.stream()
                        .filter(o -> o.getFlag() == 1)
                        .collect(Collectors.toList());
            }
        }
        //固排开关
        if ("a".equals(baseRule.getTeachingClassFixEnable())) {
            //不启用时删除本身禁排信息
            //以及教学班类型固排信息删除
            if (CollUtil.isNotEmpty(teachingClassRuleList)) {
                teachingClassRuleList = teachingClassRuleList.stream()
                        .filter(o -> o.getType() == null || o.getType() != FixType.TeachingClass.getCode())
                        .collect(Collectors.toList());
            }
        }
        return teachingClassRuleList;
    }


    public List<ArrangeTeachingClassRuleDto> removeProhibitFromCourse(Integer taskId, String schoolId, String termId, List<ArrangeTeachingClassRuleDto> teachingClassRuleList) {
        return scheduleService.removeProhibitFromCourse(taskId,schoolId,termId,teachingClassRuleList);
    }
}
